package com.soup.lab.spring.core.di;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

public class CircleReferenceTestCase {

    @Test
    public void testSelfRef() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CircleConfig.class);
        SelfRef bean = context.getBean(SelfRef.class);
        System.out.println(bean);
    }

    @Test
    public void testConstructorSelfRef() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CircleConfig.class);
        // ERROR: Requested bean is currently in creation: Is there an unresolvable circular reference?
        ConstructorSelfRef bean = context.getBean(ConstructorSelfRef.class);
        System.out.println(bean);
    }

    @Test
    public void testCircleRef() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CircleConfig.class);
        CircleRefA beanA = context.getBean(CircleRefA.class);
        CircleRefB beanB = context.getBean(CircleRefB.class);
        System.out.println(beanA);
        System.out.println(beanB);
    }


    @Configuration
    @ComponentScan
    public static class CircleConfig {
        @Bean
        public SelfRef selfRef(){
            return new SelfRef();
        }
    }

    public static class SelfRef {
        @Autowired
        private SelfRef ref;
    }

    @Component
    public static class ConstructorSelfRef {

        ConstructorSelfRef ref;
        @Autowired
        public ConstructorSelfRef(ConstructorSelfRef ref) {
            this.ref = ref;
        }
    }

    @Component
    public static class CircleRefA {

        @Autowired
        private CircleRefB ref;

    }

    @Component
    public static class CircleRefB {

        @Autowired
        private CircleRefA ref;

    }
}
